#how can show data of User as advertisement ?
127 messages · Page 1 of 1 (latest)
🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord
🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize
✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)
@snow salmon can you help me
first of all don't ping users that are not part of topic.
second of all your explanation of your problem is awfull.
add details, what ads, how it shown now, how it should be, any reference to thing that you want to achieve etc...
User is adding his details and his referral link, I will show their referrals in queue as advertisement
I tried with useEffect, but its client side fetching and its not real time, I want all advertisement in sync with all users
in your code you are not doing anything with your response, why then you even fetch it?
your pusher looks ok, do you get any messages at all through it? did you check is it work at all?
I checked with currentAd it shows null
I am using Next.js 14, I added this code in route file, do I need to use server action instead route file
I mean this , api/advertisement/getAllAds
Its printing all this values from env, so issue is not here
appId: process.env.PUSHER_APP_ID!,
key: process.env.PUSHER_KEY!,
secret: process.env.PUSHER_SECRET!,
cluster: process.env.PUSHER_CLUSTER!,
useTLS: true
pusher should have some kind of event logging, also you can add console.log to emitters and subscriptions to check are they working
error :
Ad rotation triggered: Response {type: 'basic', url: 'http://localhost:3000/api/advertisement/getAllAds', redirected: false, status: 405, ok: false, …} ....
....................
for Adbox component :
useEffect(() => {
fetch('/api/advertisement/getAllAds').then(response => {
console.log('Ad rotation triggered:', response);
}).catch(error => {
console.error('Error triggering ad rotation:', error);
});
console.log('Adbox pusher api start')
const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
forceTLS: true
});
console.log('Adbox pusher api middle')
const channel = pusher.subscribe('ad-channel');
channel.bind('ad-update', function(data:any) {
console.log('Received ad update:', data); // Check the data received
setCurrentAd(data.ad);
});
return () => {
pusher.unsubscribe('ad-channel');
channel.unbind_all();
};
}, []);
For currentAd state :
console.log error : Adbox pusher: null
my issue is I know how to fetch data through route in Next.js but unable to do with pusher
Is my tech stack right ?
I mean pusher for real time data, I mean to fetch
first of all here
export default async function GET(req: Request) {
remove default
then check your route through browser.
also, from where this url triggers? if from some external source it will not have access to your localhost:3000
got it, removed it, now that 405 error gon
gone
now its 500
error
check server logs
wait bro
what do yo mean ?
👇👇
also, from where this url triggers? if from some external source it will not have access to your localhost:3000 ?
I don't know where you call it, is it some webhook url, or is it some url that you call in your code.
see this is api route file
right now you need to check your pusher account and it should have some kind of logs
logs in server side of Next.js
null
⨯ node_modules\pusher\lib\errors.js (13:0) @ new RequestError
⨯ unhandledRejection: Error
at new RequestError (webpack-internal:///(rsc)/./node_modules/pusher/lib/errors.js:13:16)
at eval (webpack-internal:///(rsc)/./node_modules/pusher/lib/requests.js:61:17)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Timeout.eval [as _onTimeout] (webpack-internal:///(rsc)/./app/api/advertisement/getAllAds/route.ts:31:13) {
name: 'PusherRequestError',
message: 'Unexpected status code 413',
url: 'https://api-ap2.pusher.com/apps/1791291/events?auth_key=1124eb29e2343d430175&auth_timestamp=1714565710&auth_version=1.0&body_md5=9407ca774dc5539f5b0730b8a1dd27c2&auth_signature=d050297c957aeb4b2617ab130c8c74a0b4e380a73d39baf7a859b8404405380d',
error: undefined,
status: 413,
body: 'The data content of this event exceeds the allowed maximum (10240 bytes). See https://pusher.com/docs/channels/server_api/http-api#publishing-events for more info\n'
}
I am checking with pusher
The data content of this event exceeds the allowed maximum (10240 bytes)
they allow only short messagees 10kb
http errors :
The data content of this event exceeds the allowed maximum (10240 bytes). See https://pusher.com/docs/channels/server_api/http-api#publishing-events for more info
Request method: POST
Channels provides a HTTP API as the main point of interaction with your servers.
My request method was GET, why its showing POST
this errors are from pusher server logs
you are not controlling request to pusher, you can only call trigger, which will call POST to their api with your data.
they even don't have GET handler.
can you explain this
it's self explanatory,
you are calling
await pusher.trigger('ad-channel', 'ad-update', {
ad
});
which call POST request to pusher API, which show you error that your message bigger than allowed in API limits.
I removed image from backend to avoid that error (size error)
now I am getting response but not image
before:
Adbox pusher: null
Now (after) :
Adbox pusher: {_id: '6627ab3fadf957dc0af93a11', title: 'Upland', link: 'https://r.upland.me/gKuk', image: '', userId: '662
but I want images also
probably pusher not intended for that, you probably save all of this ads in your database, so you can send via pusher only update event and in your client on message from pusher you again fetch data from api.
that's what I did, or I misconcept it
I am getting data from backend
export async function GET(req: Request) {
try {
await connectDB();
const ads = await Advertisement.find({});
console.log('ads through pusher:', ads)
you sent a lot of data, I am saying send only update event
await pusher.trigger('ad-channel', 'ad-update', {upd:1});
what's upd: 1
small update event
my code is :
await pusher.trigger('ad-channel', 'ad-update', {
ad
});
but I already sent only 1 object which is ad
there is nothing upd in my code
which giant object that rejected by pusher because of size
😂 yeah
bro, what is upd
so instead you send small message
upd is short for update
you can send whatever you want
it just should be small
oh, like custom message
yes
not got this, for currentAd state
Adbox pusher: undefined
import React, { useEffect, useState } from 'react';
import Pusher from 'pusher-js';
import Image from 'next/image';
type AdType = {
_id: string;
link: string;
image: string;
}
const AdBox = () => {
const [currentAd, setCurrentAd] = useState<AdType | null>(null);
useEffect(() => {
fetch('/api/advertisement/getAllAds').then(response => {
console.log('Ad rotation triggered:', response);
}).catch(error => {
console.error('Error triggering ad rotation:', error);
});
const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
forceTLS: true
});
console.log('Adbox pusher api middle')
const channel = pusher.subscribe('ad-channel');
channel.bind('ad-update', function(data:any) {
console.log('Received ad update:', data); // Check the data received
setCurrentAd(data.ad);
});
return () => {
pusher.unsubscribe('ad-channel');
channel.unbind_all();
};
console.log('Adbox pusher:', currentAd)
return (
<div>
{currentAd && (
<div>
<Image src={currentAd.image} alt="Advertisement" width={300} height={300} layout="responsive" />
<a href={currentAd.link} target="_blank" rel="noopener noreferrer">Visit Ad</a>
</div>
)}
</div>
);
};
export default AdBox;
for
Received ad update: {upd: 1}
if it's message from console then you get update
now you need to change
channel.bind('ad-update', function(data:any) {
console.log('Received ad update:', data); // Check the data received
setCurrentAd(data.ad);
});
so it refetch data
fetch('/api/advertisement/getAllAds').then(response => {
console.log('Ad rotation triggered:', response);
}).catch(error => {
console.error('Error triggering ad rotation:', error);
});
and set it to your state
Ad rotation ads in json undefined
updated code
fetch('/api/advertisement/getAllAds')
.then(response => {
console.log('Ad rotation triggered:', response);
response.json()
})
.then(data => {
console.log('Ad rotation ads in json', data)
setCurrentAd(data);
})
.catch(error => {
console.error('Error triggering ad rotation:', error);
});
I added ad to pass object through response
route.ts
export async function GET(req: Request) {
try {
await connectDB();
const ads = await Advertisement.find({});
console.log('ads through pusher:', ads)
let currentAdIndex = 0;
setInterval(async () => {
const ad = ads[currentAdIndex];
console.log(`Sending ad: ${currentAdIndex}`, ad);
await pusher.trigger('ad-channel', 'ad-update', {
upd: 1
});
currentAdIndex = (currentAdIndex + 1) % ads.length;
}, 20000);
return NextResponse.json({ message: 'Ad rotation started', ad: ads[currentAdIndex] });
} catch (error) {
console.error('Error rotating ads:', error);
}
}
its only trigger event, which is pusher.trigger
not fetching data, I mean get request after each trigger
and now its only getting undefined for
Ad rotation ads in json
why do you need 2 then here? get data directly from response
I am getting response but its too much responses.
I will share my updated code and screenshot
const fetchAds = async() => {
try{
const response = await axios.get('/api/advertisement/getAllAds');
console.log('response', response?.data)
setCurrentAd(response?.data?.ad)
}catch(error){
console.log('Error fetching ads:', error);
}
}
useEffect(() => {
fetchAds();
const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
forceTLS: true
});
const channel = pusher.subscribe('ad-channel');
channel.bind('ad-update', function(data:any) {
console.log('Received ad update:', data);
fetchAds();
});
return () => {
pusher.unsubscribe('ad-channel');
channel.unbind_all();
};
}, []);
I changed method from fetch to async await and invoke in useEffect first then also in bind method (fetchAds())
what's wrong about it? code looks fine
its making too many request
I will show you
based on that you receive a lot ad-update update events, then you probably generating a lot of them
changes I made is added state isFetch and use it in useEffect for if condition of fetchAds invoking
const AdBox = () => {
const [currentAd, setCurrentAd] = useState<AdType | null>(null);
const [isFetch, setIsFetch] = useState<boolean>(true);
const fetchAds = async() => {
try{
const response = await axios.get('/api/advertisement/getAllAds');
setCurrentAd(response?.data?.ad)
}catch(error){
console.log('Error fetching ads:', error);
}
}
useEffect(() => {
if(isFetch){
fetchAds();
setIsFetch(false);
}
const pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_KEY!, {
cluster: process.env.NEXT_PUBLIC_PUSHER_CLUSTER!,
forceTLS: true
});
const channel = pusher.subscribe('ad-channel');
channel.bind('ad-update', function(data:any) {
console.log('Received ad update:', data); // Check the data received
fetchAds();
});
return () => {
pusher.unsubscribe('ad-channel');
channel.unbind_all();
};
}, []);
console.log('Adbox pusher:', currentAd)
return (.....
)
}
how ?
Is here I making any mistake, in pusher.trigger?
export async function GET(req: Request) {
try {
await connectDB();
const ads = await Advertisement.find({});
console.log('ads through pusher:', ads)
let currentAdIndex = 0;
setInterval(async () => {
const ad = ads[currentAdIndex];
console.log(`Sending ad: ${currentAdIndex}`, ad);
await pusher.trigger('ad-channel', 'ad-update', {
upd: 1
});
currentAdIndex = (currentAdIndex + 1) % ads.length;
}, 60000);
console.log('ad res:', ads[currentAdIndex])
return NextResponse.json({ message: 'Ad rotation started', ad: ads[currentAdIndex] });
} catch (error) {
console.error('Error rotating ads:', error);
}
}
why
setInterval(async () => {
const ad = ads[currentAdIndex];
console.log(`Sending ad: ${currentAdIndex}`, ad);
await pusher.trigger('ad-channel', 'ad-update', {
upd: 1
});
currentAdIndex = (currentAdIndex + 1) % ads.length;
}, 60000);
this in setinterval?
yes
why?
I want to invoke data from ad array in queue, like google ads, each object contain link and image, that I want to show on frontend
you need to stop your deployment of site because it basically generates thousands of events right now
I haven't deployed that updated code
don't worry
wdym? if you receiveing events then pusher works
and eventually it will start charge money
and eventually it will start charge money ?
you generating thousands of events through pusher right now
you don't need setinterval, you need to trigger single update event. that's all
after that your client will fetch all new data from server
but how it fetch after each 1 minute
you have code
channel.bind('ad-update', function(data:any) {
console.log('Received ad update:', data); // Check the data received
fetchAds();
});
that will fetch it as soon as receiveing upd signal
right now you sending thousands signals and it making thousands fetches
but how it fech after 1 minute, I set setInterval, which was wrong approach but it fetches after 1 minute, how it hapen without it
it triggers new request, that I understand but what about timing
why 1 minute? from where this 1 minute arise? you wanted update your ad in real time, your code without setinterval will update it in real time
but I want in queue that list of ads
why?
ok, I will explain you
I have users data, we can consider 1000 users
and they submit their site link and image or anything they want to promote
and its in database and I am rendering those data as advertisemnet on frontend
if there 1000 Users,
each User's advertisement will run for 1 minute, after that advertisement will change and next User's advertisement will show .
I can change time from 1 minute to 2 minutes.
I use real time cause I want to show advertisement in sync, like A user will see 'xy' advertisement then B user will see same advertsement.
I tried this with client side fetching with only useEffect but it fetches from 1st each time if I open app and If I close it starts from 1st again. So its not syncing real time, right ?
this feature I want to implement
bro, have you got my point ?
for reference this is document data
I will not help you with implementation, you have no idea what you working with, you need to read how giant ads networks work, and gain more experience in programming.
I can give you direction, if you want to be in sync you can use user UTC as point in sync, because it will be same for everyone. and setInterval should be run on client. Using websocket for this task is useless waste of resources, especially for syncing.
bro, pls help me, I already waited for so long. No one knows,
atleast now its working
I said I want data in sync, means all users can see same advertisement not different
and for senterval, I can remove it from server side, get data in array of 10 list items, then can show on client side with setinterval
is that ok ?
or should I use other option like redis, can I do that with redis ?
UTC will give you data in sync, as I said it same for everyone, deviation is insignificant for human eye.
redis or memcached is required.
but your "auction" of banners is bad, your clients will waste their money with such calculations, you need ton of additional logging for fair views calculation. it's not a single pusher websocket task, it's much more because people pay for view.
like this
const updateCurrentAd = (ads: AdType[]) => {
const minutes = new Date().getUTCMinutes();
const currentAdIndex = minutes % ads.length;
setCurrentAd(ads[currentAdIndex]);
};
const AdBox = () => {
const [ads, setAds] = useState<AdType[]>([]);
const [currentAd, setCurrentAd] = useState<AdType | null>(null);
const fetchAds = async () => {
try {
const response = await axios.get('/api/advertisement/getAllAds');
setAds(response.data.ads);
updateCurrentAd(response.data.ads);
} catch (error) {
console.error('Error fetching ads:', error);
}
};
const updateCurrentAd = (ads: AdType[]) => {
const minutes = new Date().getUTCMinutes();
const currentAdIndex = minutes % ads.length;
setCurrentAd(ads[currentAdIndex]);
};
useEffect(() => {
fetchAds();
const interval = setInterval(() => {
if (ads.length > 0) {
updateCurrentAd(ads);
}
}, 1000 * 10); // check every 10 seconds to limit checks
return () => clearInterval(interval);
}, [ads]);
something like that is minimal setup, but this still not include view amount, because each and every network and device is different it can take like 20s to fetch new data, so you need a lot of additional counter when image change, when it's loaded in DOM, how many user saw it etc......
you need to have your action alghoritm, what if new ad arrived, what if some was deleted etc......
it's freaking rabbit hole.